package com.probitcoin;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;

import com.probitcoin.BTCE.BTCEException;
import com.probitcoin.BTCE.Info;
import com.probitcoin.BTCE.OrderList;
import com.probitcoin.BTCE.Ticker;
import com.probitcoin.BTCE.Trade;

public class MainActivity extends Activity {
	
	private TextView last;
	private TextView buy;
	private TextView sell;
	private TextView your_dollars;
	private TextView your_bitcoins;
	private TextView detail_buy;
	private TextView detail_sell;
	private TextView last_updated;
	private TextView pending_orders;
	
	private Button cancel_order;
	private Button quick_buy;
	private Button quick_sell;
	
	private ImageButton reload;
	
	private BTCE btce;
	private Ticker t;
	private Info i;	
	private OrderList ao = null;  // Active orders
	
	private NumberFormat formatter;
	private static String now_str;
	
	private static final int INIT_COMPLETE = 1;
	private static final int INIT_FAILED = 0;
	private static final int NEW_DATA_COMPLETE = 2;
	private static final int NEW_DATA_FAILED = 3;
	private static final int QUICK_SELL_SUCCESS = 4;
	private static final int QUICK_SELL_FAILED = 5;
	private static final int QUICK_BUY_SUCCESS = 6;
	private static final int QUICK_BUY_FAILED = 7;
	private static final int CANCEL_SUCCESS = 8;
	private static final int CANCEL_FAILED = 9;
	private static final int AUTH_FAILED = 10;
	
	private static double FEE = 1.002;   // TODO: Get from API
	@SuppressWarnings("unused")
	private static double last_price = 0d;
	@SuppressWarnings("unused")
	private static double lowest_ask_price = 0d;
	@SuppressWarnings("unused")
	private static double highest_bid_price = 0d;
	@SuppressWarnings("unused")
	private static double funds_btc = 0d;
	@SuppressWarnings("unused")
	private static double funds_usd = 0d;
	
	
	/*
	 * ON CREATE 
	 */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_screen);
    
        formatter = new DecimalFormat("####.####");
        
        loadPrefs();
        
        initViews();

        initListeners();
    }
    

	private void loadPrefs() {
    	SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);

    	String key = sp.getString("key", "Not found");
    	String secret = sp.getString("secret", "Not found");
    	
    	if ((key.equals("Not found") || secret.equals("Not found"))
    			&&
    		(key.length() != 44 || secret.length() != 64) ) {
	    		Intent i = new Intent().setClass(this, WelcomeActivity.class);
	    		startActivity(i);
	    		finish();
    	} else {
    		// If key and secret are found, initialize btce
    		initBtce(key, secret);
    	}

    }


    /*
     * Initialize views
     */
    private void initViews() {
    	last = 			(TextView) findViewById(R.id.last_price);
    	buy = 			(TextView) findViewById(R.id.lowest_ask);
    	sell = 			(TextView) findViewById(R.id.highest_bid);
    	your_dollars = 	(TextView) findViewById(R.id.funds_usd);
    	your_bitcoins = (TextView) findViewById(R.id.funds_btc);
    	detail_buy = 	(TextView) findViewById(R.id.detail_buy);
    	detail_sell = 	(TextView) findViewById(R.id.detail_sell);
    	last_updated =  (TextView) findViewById(R.id.last_updated);
    	pending_orders =(TextView) findViewById(R.id.title_pending_orders);
    	
    	quick_buy = 	(Button) findViewById(R.id.buy_btc);
    	quick_sell = 	(Button) findViewById(R.id.sell_btc);
    	cancel_order = 	(Button) findViewById(R.id.cancel_order);
    	reload = 		(ImageButton) findViewById(R.id.reload);
    	
    }
    
    /*
     * Initialize event listeners
     */
    private void initListeners() {
    	
    	quick_buy.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				if((round(i.info.funds.usd/(t.sell*FEE),4)) < 0.1) {
					Log.d("Insuficient USD", "Sorry, the minimum amount buy is 0.01 BTC");
					showToast("Sorry, the minimum amount to buy is 0.01 BTC");
				} else {
					quickBuy();
				}
			}
		});

    	quick_sell.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				if (i.info.funds.btc < 0.01) {
					Log.d("Insuficient BTC", "Sorry, you need to have at least 0.01 BTC to be able to trade");
					showToast("Sorry, you need to have at least 0.01 BTC to be able to trade");
				} else {
					quickSell();
				}
			}
		});

    	reload.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				queryNewData();
			}
		});
    	
    	cancel_order.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				cancelOrder();
			}
		});
    }
    
    
    
    /*
     * Initialize connection with BTC-e 
     */
    private void initBtce(final String key, final String secret) {
		final ProgressDialog ringProgressDialog = 
				ProgressDialog.show(MainActivity.this, "Please wait ...", "Contacting BTC-e ...", true);
		ringProgressDialog.setCancelable(false);
		Thread th = new Thread() {
			@Override
			public void run() {
				try {
					btce = new BTCE();
//					btce.setAuthKeys("SI7X35CZ-KBG6K6UI-JH1FRH2W-AVQ2FWKE-Z9405IBW","dfc21b166dcf97efca3eaff0b62eacff0770d94ebf02de188eaea56166997d09");
					btce.setAuthKeys(key, secret);
					btce.setAuthRequestLimit(15000);
					btce.setRequestLimit(1000);
					
					if(btce.getInfo().success != 1) {
						Message msg = Message.obtain();
			            msg.what = INIT_FAILED;
			            handler.sendMessage(msg);
			            return;
					} else {
						
					}
					
				} catch (BTCEException e) {
					e.printStackTrace();
					Message msg = Message.obtain();
		            msg.what = INIT_FAILED;
		            handler.sendMessage(msg);
				}
				Message msg = Message.obtain();
	            msg.what = INIT_COMPLETE;
	            handler.sendMessage(msg);
				ringProgressDialog.dismiss();
			}
		};
		th.start();
	}
    
    
    
    
    /*
     * Get new data from BTC-e
     */
    public void queryNewData() {
		final ProgressDialog ringProgressDialog = 
				ProgressDialog.show(MainActivity.this, "Please wait ...",	"Querying new data ...", true);
		ringProgressDialog.setCancelable(false);
		Thread th = new Thread() {
			@Override
			public void run() {
				try {
					t = btce.getTicker(BTCE.Pairs.BTC_USD);
					i = btce.getInfo();
					ao = btce.getActiveOrders();
					
					Log.d("Ticker", t.toString());
					Log.d("Info", i.toString());
					Log.d("Active orders", ao.toString());
					
					last_price = t.last;
					lowest_ask_price = t.buy;
					highest_bid_price = t.sell;
					funds_btc = i.info.funds.btc;
					funds_usd = i.info.funds.usd;
				} catch (BTCEException e) {
					e.printStackTrace();
					Message msg = Message.obtain();
		            msg.what = NEW_DATA_FAILED;
		            handler.sendMessage(msg);
				}
				
				ringProgressDialog.dismiss();
				
				Message msg = Message.obtain();
	            msg.what = NEW_DATA_COMPLETE;
	            handler.sendMessage(msg);
				
			}
		};
		th.start();
		
	}
    
    
    
    
    /*
     * Sells all BTC at the highest bid price
     */
    private void quickSell() {
    	
    	final String pair =	BTCE.Pairs.BTC_USD ;
    	final String trade_type = BTCE.TradeType.SELL ;
		final double price = 1000; //t.sell;
		final double amount = i.info.funds.btc;
		
		
		new AlertDialog.Builder(MainActivity.this)
        .setTitle("Sell BTC")
        .setMessage("Sell "+amount+" BTC for "+round(amount*(price*1.002),4)+" USD?")
        .setPositiveButton("YES",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                    	final ProgressDialog ringProgressDialog = 
                				ProgressDialog.show(MainActivity.this, "Please wait ...",	"Creating sell order ...", true);
                		ringProgressDialog.setCancelable(true);
                		Thread th = new Thread() {
                			@Override
                			public void run() {
                				Trade trade=null;
                				try {
                					trade = btce.trade(pair,trade_type,price,amount);
                				} catch (BTCEException e) {
                					e.printStackTrace();
                					Message msg = Message.obtain();
                		            msg.what = QUICK_SELL_FAILED;
                		            handler.sendMessage(msg);
                				}
                				ringProgressDialog.dismiss();
                				
                				Message msg = Message.obtain();
                	            msg.what = QUICK_SELL_SUCCESS;
                	            handler.sendMessage(msg);
                	            
                	            Log.d("Quick Sell", trade.toString());
                			}
                		};
                		th.start();
                    }
                })
        .setNegativeButton("NO", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                // Nothing...
            }
        }).show();
	}
    
    
    
    
    /*
     * Buys BTC using all the funds in dollars at the lowest ask price
     */
	private void quickBuy() {
	    	
		final String pair = BTCE.Pairs.BTC_USD ;
		final String trade_type = BTCE.TradeType.BUY ;
		final double price = 409; // t.buy ;
		final double amount = round(i.info.funds.usd/(price*FEE),4);
		
		new AlertDialog.Builder(MainActivity.this)
        .setTitle("Buy BTC")
        .setMessage("Buy "+amount+" BTC for "+formatter.format(price*amount)+" USD?")
        .setPositiveButton("YES",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {

                    	final ProgressDialog ringProgressDialog = 
                				ProgressDialog.show(MainActivity.this, "Please wait ...",	"Creating buy order ...", true);
                		ringProgressDialog.setCancelable(true);
                		
                		Thread th = new Thread() {
                			@Override
                			public void run() {
                				Trade trade=null;
                				try {
                					trade = btce.trade(pair,trade_type,price,amount);
                					
                				} catch (BTCEException e) {
                					e.printStackTrace();
                					Message msg = Message.obtain();
                		            msg.what = QUICK_BUY_FAILED;
                		            handler.sendMessage(msg);
                				}
                				ringProgressDialog.dismiss();
                				
                				Message msg = Message.obtain();
                	            msg.what = QUICK_BUY_SUCCESS;
                	            handler.sendMessage(msg);
                	            
                	            Log.d("Quick Buy", trade.toString());
                			}
                		};
                		th.start();
                    }
                })
        .setNegativeButton("NO", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                // Nothing...
            }
        }).show();
		
		
		
			
	}
    
    
	
    /*
     * Cancel pending order
     * TODO Free: Cancel oldest order (one at a time)
     * TODO Pro: Cancel specified order
     */
    private void cancelOrder() {
 
    	final int order_id = (int) ao.info.orders[0].order_id;
    	
    	new AlertDialog.Builder(MainActivity.this)
        .setTitle("Cancel order")
        .setMessage("Cancel pending order?")
        .setPositiveButton("YES",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                    	final ProgressDialog ringProgressDialog = 
                				ProgressDialog.show(MainActivity.this, "Please wait ...",	"Cancelling order ...", true);
                		ringProgressDialog.setCancelable(true);
                		
                		Thread th = new Thread() {
                			@Override
                			public void run() {
                				try {
                					btce.cancelOrder(order_id);
                				} catch (BTCEException e) {
                					e.printStackTrace();
                					Message msg = Message.obtain();
                		            msg.what = CANCEL_FAILED;
                		            handler.sendMessage(msg);
                				}
                				ringProgressDialog.dismiss();
                				
                				Message msg = Message.obtain();
                	            msg.what = CANCEL_SUCCESS;
                	            handler.sendMessage(msg);
                	            
                	            Log.d("Cancel order", "Cancel order");
                			}
                		};
                		th.start();
                    }
                })
        .setNegativeButton("NO", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                // Nothing
            }
        }).show();
    }
	
	
	
	
    /*
     * Handle messages
     */
    @SuppressLint("HandlerLeak")
	private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
        	Intent i = new Intent();
            switch(msg.what){
            case INIT_COMPLETE:
            	queryNewData();
                break;
                
            case AUTH_FAILED:
        		i.setClass(getApplicationContext(), WelcomeActivity.class);
        		i.putExtra("ERROR", "AUTH_FAILED");
        		startActivity(i);
            	break;
                
            case INIT_FAILED:
            	showToast("An error ocurred when trying connect to BTC-e");
        		i.setClass(getApplicationContext(), WelcomeActivity.class);
        		i.putExtra("ERROR", "INIT_FAILED");
        		startActivity(i);
            	break;

            case NEW_DATA_COMPLETE:
            	updateDateTime();
            	reloadViews();
            	break;
            	
            case NEW_DATA_FAILED:
            	showToast("An error ocurred when trying to fetch new data");
            	break;
            	
            case QUICK_SELL_SUCCESS:
            	showToast("Sell order created successfully.");
            	queryNewData();
            	reloadViews();
            	break;
            	
            case QUICK_SELL_FAILED:
            	showToast("An error ocurred when trying to create the sell order");
            	break;
            	
            case QUICK_BUY_SUCCESS:
            	showToast("Buy order created successfully");
            	queryNewData();
            	reloadViews();
            	break;
            	
            case QUICK_BUY_FAILED:
            	showToast("An error ocurred when trying to create the buy order");
            	break;
            
            case CANCEL_SUCCESS:
            	showToast("Order cancelled successfully");
            	queryNewData();
            	reloadViews();
            	break;
            	
            case CANCEL_FAILED:
            	showToast("An error ocurred when trying to cancel the pending order");
            	break;
            }
        }    	
    };
    

    
    /*
     * Updates views using the new data
     */
	private void reloadViews() {
    	try {
    		final double price_buy = t.buy ;
    		final double amount_buy = round(i.info.funds.usd/(price_buy*1.002),4);
    		
    		final double price_sell = t.sell ;
    		final double amount_sell = round(i.info.funds.btc*(price_sell*1.002),4);
    		
			last.setText(formatter.format(t.last));
			buy.setText(formatter.format(t.buy));
			sell.setText(formatter.format(t.sell));
			your_dollars.setText(formatter.format(i.info.funds.usd));
			your_bitcoins.setText(formatter.format(i.info.funds.btc));
			
			last_updated.setText("Last updated " + now_str);
			
			detail_buy.setText("Buy " + 
							formatter.format(amount_buy) + 
							" BTC\nfor " + 
							formatter.format(price_buy*amount_buy) + 
							" USD");
			
			detail_sell.setText("Sell " + 
							formatter.format(amount_sell) + 
							" BTC\nfor " + 
							formatter.format(price_sell*amount_sell) + 
							" USD");
			
			if (ao.success==1) {
				pending_orders.setVisibility(View.VISIBLE);
				cancel_order.setVisibility(View.VISIBLE);
				
			} else {
				pending_orders.setVisibility(View.INVISIBLE);
				cancel_order.setVisibility(View.INVISIBLE);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
    }

	
    
    @SuppressLint("SimpleDateFormat")
	private void updateDateTime() {
    	Calendar now = Calendar.getInstance();
    	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		now_str = sdf.format(now.getTime());
    }


    
	private static double round(double value, int places) {
	    if (places < 0) throw new IllegalArgumentException();

	    long factor = (long) Math.pow(10, places);
	    value = value * factor;
	    long tmp = Math.round(value);
	    return (double) tmp / factor;
	}
	
	private void showToast(String text) {
		Toast.makeText(getApplicationContext(),	text, Toast.LENGTH_SHORT).show();
	}
    
    
}
